using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Threading;
using System.Xml.Serialization;
using System.ComponentModel;
using System.Windows.Forms;

namespace MetX.Data
{

	[Serializable]
	public enum xlgTokenType
	{
		String,
		Path,
		ExistingPath,
		InsuredPath,
		InsuredFile,
		Filename,
		Int,
		DateTime,
		Guid,
		SecurityIssue,
		ConnectionString,
		EmailAddress,
		URL,
		IPAddress,
		HostName,
		DomainUser,
		Template,
		PipelineSettings,
		StepSettings,
		Xsd,
		Xml,
		Sql,
		GatherOutput,
		GatherPowerShell,
		TemplatesFolder,
		MyTemplatesFolder,
		Password
	}

	[Serializable]
	public enum xlgTokenListScope
	{
		PipelineFile = 10,
		GenTime = 100,
		GenStep = 1000,
		UserDefaults = 5,
		SharedStandards = 50,
		XlgDefaults = 2,
		MachineSpecific = 0
	}

	[Serializable]
	public class xlgTokenList
	{
		[XmlAttribute]
		public string ID;

		[XmlAttribute]
		public xlgTokenListScope Scope;

		[XmlArray("Tokens"), XmlArrayItem("Token")]
		public BindingList<xlgToken> Tokens;

		[XmlIgnore]
		public xlgToken this[string TokenName]
		{
			get
			{
				foreach (xlgToken CurrToken in Tokens)
				{
					if (CurrToken.Name == TokenName)
						return CurrToken;
				}
				return null;
			}
		}

		public int Resolve(xlgTokenResolver Resolver)
		{
			int Count = 0;
			foreach (xlgToken CurrToken in Tokens)
			{
				if (!CurrToken.IsResolved)
				{
					if (string.IsNullOrEmpty(CurrToken.Value) || 
						(CurrToken.Value.Contains("(_") && CurrToken.Value.Contains("_)")) || 
						(CurrToken.Value.Contains("{") && CurrToken.Value.Contains("}")))
					{
						Resolver.ResolveToken(CurrToken);
						Count++;
					}
				}
			}
			return Count;
		}

		public void RestoreToDefaults(xlgTokenResolver Resolver)
		{
			foreach (xlgToken CurrToken in Tokens)
				{
					if (CurrToken.IsResolved && CurrToken.Default != null)
						CurrToken.Value = null;
				}
		}


		public xlgTokenList Clone()
		{
			return xlgTokenList.FromXml(this.OuterXml());
		}

		public static xlgTokenList FromXml(string XmlDoc)
		{
			return MetX.xml.FromXml<xlgTokenList>(XmlDoc);
		}

		public void SaveFile(string Filename)
		{
			MetX.xml.SaveFile<xlgTokenList>(Filename, this);
		}

		public static xlgTokenList LoadFile(string Filename)
		{
			return MetX.xml.LoadFile<xlgTokenList>(Filename);
		}

		public string OuterXml()
		{
			return MetX.xml.ToXml<xlgTokenList>(this, true);
		}

		public xlgTokenList() 
		{
			this.Tokens = new BindingList<xlgToken>();
		}

		public xlgTokenList(string ID, xlgTokenListScope Scope)
		{
			this.ID = ID;
			this.Scope = Scope;
			this.Tokens = new BindingList<xlgToken>();
		}
	}


    [Serializable]
    public class xlgTokenListManager
    {
        public List<xlgTokenList> Lists;
		public xlgTokenList xlgDefaults;
		public xlgTokenList MyDefaults;

        public xlgTokenListManager() { Lists = new List<xlgTokenList>(); }

        public static xlgTokenListManager FromXml(string XmlDoc)
        {
            return MetX.xml.FromXml<xlgTokenListManager>(XmlDoc);
        }

        public string OuterXml()
        {
            return MetX.xml.ToXml<xlgTokenListManager>(this, true);
        }

        public xlgTokenList FindAllByTokenType(xlgTokenType ToFind)
        {
            xlgTokenList ret = new xlgTokenList();
            foreach (xlgTokenList CurrList in this.Lists)
                foreach (xlgToken CurrToken in CurrList.Tokens)
                    if (CurrToken.As == ToFind)
                        ret.Tokens.Add(CurrToken);
            return ret;
        }

        public xlgTokenList FindAllByTokenType(xlgTokenType ToFind1, xlgTokenType ToFind2)
        {
            xlgTokenList ret = new xlgTokenList();
            foreach (xlgTokenList CurrList in this.Lists)
                foreach (xlgToken CurrToken in CurrList.Tokens)
                    if (CurrToken.As == ToFind1 || CurrToken.As == ToFind2)
                        ret.Tokens.Add(CurrToken);
            return ret;
        }

		public xlgToken SetToken(string TokenName, string NewValue)
		{
			xlgToken Candidate = null;
            foreach (xlgTokenList CurrList in this.Lists)
                foreach (xlgToken CurrToken in CurrList.Tokens)
					if (CurrToken.Name == TokenName)
					{
						if (Candidate == null || (int)CurrList.Scope > (int)Candidate.Parent.Scope)
						{
							if (Candidate != null)
								Candidate.Parent = null;
							Candidate = CurrToken;
							Candidate.Parent = CurrList;
						}
					}
			if (Candidate != null)
			{
				Candidate.Value = NewValue;
				Candidate.IsResolved = true;
				Candidate.Parent = null;
			}
			return Candidate;
		}

		public xlgToken Find(string TokenName)
		{
			xlgToken Candidate = null;
			foreach (xlgTokenList CurrList in this.Lists)
				foreach (xlgToken CurrToken in CurrList.Tokens)
					if (CurrToken.Name == TokenName)
					{
						if (Candidate == null || (int)CurrList.Scope > (int)Candidate.Parent.Scope)
						{
							if (Candidate != null)
								Candidate.Parent = null;
							Candidate = CurrToken;
							Candidate.Parent = CurrList;
						}
					}
			if (Candidate != null)
				Candidate.Parent = null;
			return Candidate;
		}
	}

	/// <summary>
	/// Represents a named value to resolve before generation and to insert into the generated xml
	/// </summary>
	[Serializable, XmlRoot("Token")]
	public class xlgToken
	{
		[XmlIgnore]
		public xlgTokenList Parent;

		private string _Name;
		private string _Value;
		private xlgTokenType _As;
		private string _Prompt;
		private string _Default;

		private bool _IsResolved;

		[XmlAttribute]
		public bool IsResolved
		{
			get { return _IsResolved; }
			set { _IsResolved = value; }
		}

		[XmlIgnore]
		public bool NeedsResolution
		{
			get
			{
				if (string.IsNullOrEmpty(Value))
				{
					if (!string.IsNullOrEmpty(Default))
					{
						// if ((Default.Contains("(_") && Default.Contains("_)")) || (Default.Contains("{") && Default.Contains("}")))
						return true;
					}
				}
				else if ((Value.Contains("(_") && Value.Contains("_)")) || (Value.Contains("{") && Value.Contains("}")))
					return true;
				return false;
			}
		}
			

		[XmlAttribute]
		public string Default
		{
			get { return _Default; }
			set { _Default = value; }
		}
		
			
		[XmlAttribute]
		public string Prompt
		{
			get { return _Prompt; }
			set { _Prompt = value; }
		}


		[XmlAttribute]
		public xlgTokenType As
		{
			get { return _As; }
			set { _As = value; }
		}


		[XmlAttribute]
		public string Name
		{
			get
			{
				
				return _Name;
			}
			set
			{
				_Name = value;
			}
		}

		[XmlAttribute]
		public string Value
		{
			get
			{
				return _Value;
			}
			set
			{
				_Value = value;
			}
		}

		public xlgToken()
		{
		}

		public xlgToken(xlgTokenList Parent, string Name, string Value)
		{
			this.Parent = Parent;
			this._Name = Name;
			this._Value = Value;
		}

	}
}
